package log;

import static log.LogConstants.Block;
import static log.LogConstants.Participant;
import static log.LogConstants.Phase;
import static log.LogConstants.TimeEnd;
import static log.LogConstants.Training;
import static log.LogConstants.Trial;
import static log.LogConstants.When;
import static log.LogConstants.Mode;
import static log.LogConstants.Technique;

import static run.ScenarioManager.CINE_LOG_FREQUENCY;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;

import technique.misc.MODE;

public class Merger {
	
	protected BufferedReader cinematicReader, logReader, logReader2;
	
	/**
	 * Factor names and their corresponding column number for cinematic files
	 */
	protected HashMap<String, Integer> cinematicFactors = new HashMap<String, Integer>();
	
	/**
	 * Factor names and their corresponding column number for log files
	 */
	protected HashMap<String, Integer> logFactors = new HashMap<String, Integer>();
	
	/**
	 * Final set of not-empty, not-overlapping cinematic files to be written.
	 */
	protected String[] cinematicFileNames;
	/**
	 * Final set of not-empty, not-overlapping log files to be written.
	 */
	protected String[] logFileNames;
	
	protected ArrayList<Integer> lastLogIndexOfBlock = new ArrayList<Integer>();
	protected ArrayList<Integer> lastCinematicIndexOfBlock = new ArrayList<Integer>();
	
	protected ArrayList<String> logFileLines = new ArrayList<String>();
	protected ArrayList<String> cinematicFileLines = new ArrayList<String>();
	
	protected String[] cinematicFactorValues;
	protected String[] logFactorValues;
	
	protected ArrayList<String> cinematicAdditionalValues = new ArrayList<String>();
	protected ArrayList<String> logAdditionalValues = new ArrayList<String>();
	
	protected BufferedWriter cinematicWriter;
	protected BufferedWriter logWriter;
	
	public void merge(String cinematicFolder, String logFolder, String cinematicTargetName, String logTargetName, String[] _cinematicFileNames, String[] _logFileNames) {
		
		// For column names
		boolean firstFile = true;
		
		// There should be the same number of cinematic and log files...
		if (_cinematicFileNames.length != _logFileNames.length) {
			
			System.err.println("Different number of files: " + _cinematicFileNames.length + ", " + _logFileNames.length);
			
		}
		
		// Displaying the missing files if any
		
		int logCursor = 0, cineCursor = 0;

		ArrayList<String> logFileList = new ArrayList<String>();
		ArrayList<String> cinematicFileList = new ArrayList<String>();
		
		while (logCursor < _logFileNames.length) {
			
			if (!_logFileNames[logCursor].endsWith(logTargetName)) {
				
				// System.out.println(_logFileNames[logCursor]);
				
				// Same participant, date and hour
				while (cineCursor < _cinematicFileNames.length && 
							( _cinematicFileNames[cineCursor].endsWith(cinematicTargetName)
							|| !_logFileNames[logCursor].endsWith(_cinematicFileNames[cineCursor].substring(_cinematicFileNames[cineCursor].indexOf("_"))) )
				) {
					
					// System.out.println("\t" + _cinematicFileNames[cineCursor].substring(_cinematicFileNames[cineCursor].indexOf("_")));
					
					cineCursor++;
					
				}
				
				if (cineCursor < _cinematicFileNames.length) {
					cinematicFileList.add(_cinematicFileNames[cineCursor]);
					logFileList.add(_logFileNames[logCursor]);
				} else {
					System.err.println("The log file " + _logFileNames[logCursor] + " does not fit any cinematic file. Or so it seems.");
				}
				
			}
			
			logCursor++;
			cineCursor = 0;
			
		}
		
		// Here it's more or less guaranteed that the files have similar names two by two
		
		/*
		 * Removing redundant files:
		 * A file is useless if its first PBT are superior or equal to these of an older file.
		 * UNLESS it's a training ? Baaah screw training.
		 * 
		 * This is done only on log files, we expect cinematic files to follow
		 */
		
		// Reordering files by increasing creation date, according to their name
		// The most recent files are thus last in the lists
		
		Comparator<String> comp = new Comparator<String>() {
			public int compare(String o1, String o2) {
				return new Integer(myOwnDate(o1)).compareTo( new Integer(myOwnDate(o2)) );
			}
		};
		
		Collections.sort(cinematicFileList, comp);
		Collections.sort(logFileList, comp);
		
		String fOld, fNew, lineOld = null, lineNew = null;
		int firstBlockOld, firstBlockNew, pOld, pNew;
		
		// Check emptiness
		
		try {
			
			for ( int i = 0 ; i < logFileList.size() ; i++ ) {
				
				logReader = new BufferedReader(new FileReader(logFolder+logFileList.get(i)));
				
				logReader.readLine();
				
				if (logReader.readLine() == null) {
					
					System.out.println("Empty: " + logFileList.get(i));
					
					logFileList.remove(i);
					cinematicFileList.remove(i);
				}
				
			}
			
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException ioe) {
			ioe.printStackTrace();
		}
		
		System.out.println();
		System.out.println("Empty files are removed, in theory.");
		System.out.println();
		
		for (int i = 1 ; i < logFileList.size() ; i++) {
			
			try {
				
				fNew = logFileList.get(i);		// newer
				logReader2 = new BufferedReader(new FileReader(logFolder+fNew));
				
				fOld = logFileList.get(i-1); 	// older
				logReader = new BufferedReader(new FileReader(logFolder+fOld));
				
				// First lines
				logReader.readLine();
				logReader2.readLine();
				
				lineOld = logReader.readLine();
				lineNew = logReader2.readLine();
				
				if (lineOld == null || lineNew == null) {
					System.out.println("Ah shit.");
					return;
				}
				
				pOld = Integer.parseInt(lineOld.split(",")[ 0 ]);
				pNew = Integer.parseInt(lineNew.split(",")[ 0 ]);
				
				// TODO id of columns...
				firstBlockOld = Integer.parseInt(lineOld.split(",")[ 2 ]);
				firstBlockNew = Integer.parseInt(lineNew.split(",")[ 2 ]);
			
				if (pOld == pNew && firstBlockOld >= firstBlockNew) {
					
					System.out.println("Removing " + logFileList.get(i-1) + " and " + cinematicFileList.get(i-1));
					// System.out.println("Comparing to " + logFileList.get(i));
					// System.out.println("\t" + lineOld + "\n\t" + lineNew);
					
					logFileList.remove(i-1);
					cinematicFileList.remove(i-1);
					
					// Keep checking
					i--;
					
				}
					
			} catch (NumberFormatException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
		
		}
		
		System.out.println("########## Files kept ##########");
		System.out.println();
		for (String s : logFileList) {
			System.out.println(s);
		}
		System.out.println();
		System.out.println("################################");
		
		/*
		 * Here we are sure (~) that file contents do not cross.
		 * Now we need to check that the last and first blocks of two contiguous files do not cross either.
		 * That's done by skipping lines (we don't alter the log files).
		 */
		
		int lastParticipantOfLastFile = -1;
		int lastBlockOfLastFile;
		
		/*
		 * Time spent above the surface in a given trial
		 */
		long timeSpentAbove, timeSpentJumping;
		/*
		 * Nb jumps Coarse to Coarse
		 */
		int nbJumpsCC = 0;
		
		cinematicFileNames = new String[cinematicFileList.size()];
		for (int i = 0 ; i < cinematicFileList.size() ; i++) {
			cinematicFileNames[i] = cinematicFileList.get(i);
		}
		logFileNames = new String[logFileList.size()];
		for (int i = 0 ; i < logFileList.size() ; i++) {
			logFileNames[i] = logFileList.get(i);
		}
		
		try {
			
			lastBlockOfLastFile = -10;
			
			cinematicWriter = new BufferedWriter(new FileWriter(cinematicFolder+cinematicTargetName));
			logWriter = new BufferedWriter(new FileWriter(logFolder+logTargetName));
			
			for (int i = 0 ; i < logFileNames.length ; i++) {
				
				String cinematicFile = cinematicFileNames[i];
				String logFile = logFileNames[i];
				
				System.out.println("Adding file " + cinematicFile  + " and " + logFile);
				
				cinematicReader = new BufferedReader(new FileReader(cinematicFolder+cinematicFile));
				logReader = new BufferedReader(new FileReader(logFolder+logFile));
				
				String cLine, lLine;
				
				if (firstFile) {
					
					// Reading column headers
					// TODO put that earlier in the file
					
					cLine = cinematicReader.readLine();
					lLine = logReader.readLine();
					
					String[] factorNames = cLine.split(",");
					
					int j = 0;
					for (String fn : factorNames) {
						cinematicFactors.put(fn, new Integer(j));
						j++;
					}
					
					factorNames = lLine.split(",");
					j = 0;
					for (String fn : factorNames) {
						logFactors.put(fn, new Integer(j));
						j++;
					}
					
					// Adding more columns if needed
					
					cinematicFileLines.add(cLine + "Percent.Of.Trial,In.Trial"); // TODO hm.
					logFileLines.add(lLine+ "Time.Spent.Above.Surface,Time.Spent.Jumping,Nb.Jumps.CC,Mode.Switch.Time,Nb.Finger.Released,MST2,NFR2,");
					
					firstFile = false;
					
				} else {
					
					// Skipping the column titles
					
					cinematicReader.readLine();
					logReader.readLine();
					
				}
				
				boolean firstCinematic = false;
				int trial, currentTrial;
				int oldBlock = -1, block = -1;
				
				// Log files are read first, then cinematics.
				
				while( (lLine=logReader.readLine()) != null ) {
				
					timeSpentAbove = 0;
					timeSpentJumping = 0;
					nbJumpsCC = 0;
					
					logFactorValues = lLine.split(",");
					
					removeNulls(logFactorValues);
					
					trial = Integer.parseInt(logFactorValues[ logFactors.get(Trial).intValue() ]);
					block = Integer.parseInt(logFactorValues[ logFactors.get(Block).intValue() ]);
					
					if (lastParticipantOfLastFile != Integer.parseInt(logFactorValues[ logFactors.get(Participant).intValue() ])) {
						
						// Different participant: we can write and reset.
						
						writeAndReset(lastParticipantOfLastFile);
						
						lastParticipantOfLastFile = Integer.parseInt(logFactorValues[ logFactors.get(Participant).intValue() ]);
						lastBlockOfLastFile = -1;
						oldBlock = -1;
						
						System.out.println();
						
					} else if (block <= lastBlockOfLastFile) {
						
						// Same participant and current block is inferior to the last block of the last file
						// -> we remove the corresponding old data from the table to be written
						
						System.out.println("Redundancy: removing from line " + lastLogIndexOfBlock.get(block) + " (block " + block + ")");
						
						/*
						System.out.println("Test :");
						System.out.println(logFileLines.get( lastLogIndexOfBlock.get(block) - 1));
						System.out.println(logFileLines.get( lastLogIndexOfBlock.get(block) ));
						*/
						
						int start = lastLogIndexOfBlock.get(block).intValue();
						int stop = logFileLines.size();
						
						for (int j = start ; j < stop ; j++) {
							logFileLines.remove(start);
						}
						
						start = lastCinematicIndexOfBlock.get(block).intValue();
						stop = cinematicFileLines.size();
						
						for (int j = lastCinematicIndexOfBlock.get(block).intValue() ; j < cinematicFileLines.size() ; j++) {
							cinematicFileLines.remove(start);
						}
						
						lastBlockOfLastFile = block-1;
						
					}
					
					if (block > oldBlock) {
						oldBlock = block;
						
						lastLogIndexOfBlock.add(block, new Integer(logFileLines.size()) );
						lastCinematicIndexOfBlock.add(block, new Integer(cinematicFileLines.size()) );
					}
					
					firstCinematic = true;
					
					long trialStart = 0;
					
					ArrayList<Long> timeStamps = new ArrayList<Long>();
					ArrayList<MODE> modes = new ArrayList<MODE>();
					int line = 0;
					int modeSwitchTime = 0, modeSwitchTime2 = 0;
					boolean oneFingerLift = true, ofl2 = true;
					
					boolean gotThereAtLeastOnce = false;
					int nbCinematicRead = 0;
					
					while( (cLine=cinematicReader.readLine()) != null ) {
						
						cinematicFactorValues = cLine.split(",");
						
						removeNulls(cinematicFactorValues);
						
						if (cinematicFactorValues[ cinematicFactors.get(Trial).intValue() ].isEmpty()) {
							continue;
						}
						
						currentTrial = Integer.parseInt(cinematicFactorValues[ cinematicFactors.get(Trial).intValue() ]);
						if (currentTrial != trial) {
							// System.out.println("new trial");
							
							if (nbCinematicRead == 0 && currentTrial > 0) {
								System.out.println("#### cTrial " + currentTrial + ", trial " + trial);
							}
							
							break;
						} 
						
						nbCinematicRead++;
						
						boolean inTrial = ( cinematicFactorValues[ cinematicFactors.get(Phase).intValue() ].equalsIgnoreCase("Trial") 
								&& cinematicFactorValues[ cinematicFactors.get(Training).intValue() ].equalsIgnoreCase("false") );
						long when = Long.parseLong(cinematicFactorValues[ cinematicFactors.get(When).intValue() ]);
						
						if (inTrial) {
							
							// System.out.println("new line");
							
							if (firstCinematic) {
								trialStart = when;
								firstCinematic = false;
							}
							
							additionalFields(trialStart);
							
							MODE newMode = null;
							
							try {
								
								newMode = MODE.valueOf( cinematicFactorValues[ cinematicFactors.get(Mode).intValue() ] );
								modes.add(newMode);
								timeStamps.add(when);
								
								/*
								 * "Time spent jumping" is time with no event for more than 
								 * CINE_LOG_FREQUENCY (with a slight multiplier, just in 
								 * case) and from Coarse to Coarse. However in some cases
								 * Coarse only comes after Precise, so this has to be investigated.
								 * 
								 * Basically, looking for C P* pause P* C
								 */
								
								if (line > 1 && modes.get(line).compareTo(MODE.COARSE) == 0) {
									
									// Current mode is Coarse
									
									if (modes.get(line-1).compareTo(MODE.COARSE) != 0) {
										
										// Case 1: there's just been a mode switch to Coarse
										// Skimming through the previous logs until a time lapse is found
										// (or a Coarse)
										
										for (int j = line ; j > 0 ; j--) {
											
											if (timeStamps.get(j) - timeStamps.get(j-1) > CINE_LOG_FREQUENCY * 2) {
												
												// There's been a time lapse in the Precise phase
												// If that half-phase is short enough, we continue looking.
												// Also if the time lapse was immediately during the mode switch.
												
												if (j == line || timeStamps.get(line) - timeStamps.get(j) < CINE_LOG_FREQUENCY * 4) {
													
													// The other side of the lapse...
													
													for (int k = j-1 ; k > 0 ; k--) {
														
														if (modes.get(k).compareTo(MODE.COARSE) == 0) {
															
															// Found the previous Coarse phase.
															// If the previous Precise half-phase was short enough, that's a jump
															
															if (timeStamps.get(j-1) - timeStamps.get(k) < CINE_LOG_FREQUENCY * 4) {
																
																timeSpentJumping += timeStamps.get(line) - timeStamps.get(k);
																nbJumpsCC++;
																
																if ( cinematicFactorValues[ cinematicFactors.get(Technique).intValue() ].contains("Stare") ) {
																	System.out.println("ERRONEOUS JUMP 1!");
																}
																
															}
															
															break;
															
														}
														
													}
													
												} else {
													// Too long, that's a full Precise phase
												}
												
												break;
												
											} 
											
											if (modes.get(j).compareTo(MODE.COARSE) == 0) {
												
												// No time lapse in Precise before getting back to Coarse
												// Still, the Precise phase could be short enough to be considered a jump
												// Too long and it's a normal Precise phase.
												
												if (timeStamps.get(line) - timeStamps.get(j) < CINE_LOG_FREQUENCY * 4) {
													
													timeSpentJumping += timeStamps.get(line) - timeStamps.get(j);
													nbJumpsCC++;
													
													if ( cinematicFactorValues[ cinematicFactors.get(Technique).intValue() ].contains("Stare") ) {
														System.out.println("ERRONEOUS JUMP 3!");
													}
													
												}
												
												break;
											}
											
										}
										
									} else {
										
										// Case 2: looking for a time lapse from the last Coarse event
										
										if (timeStamps.get(line) - timeStamps.get(line-1) > CINE_LOG_FREQUENCY * 4) {
												
											timeSpentJumping += timeStamps.get(line) - timeStamps.get(line-1);
											nbJumpsCC++;
											
											if ( cinematicFactorValues[ cinematicFactors.get(Technique).intValue() ].contains("Stare") ) {
												System.out.println("ERRONEOUS JUMP 2!");
											}
											
										}
										
									}
									
									/*
									 * "Time above surface" is time with no event for more than 
									 * CINE_LOG_FREQUENCY (with a slight multiplier, just in 
									 * case).
									 */
									
									if (line > 1 
											&& timeStamps.get(line) - timeStamps.get(line-1) > CINE_LOG_FREQUENCY * 2) {
										
										timeSpentAbove += timeStamps.get(line) - timeStamps.get(line-1);
										
									}
									
								} else {
									
									// Precise mode
									// Looking for mode switch times
									
									if (line > 1) {
										
										if (modes.get(line-1).compareTo(MODE.COARSE) == 0) {
										
											// There's just been a mode switch to Precise.
											
											// If "short" it's a one-finger lift, if not it's a two-finger lift.
											oneFingerLift &= (timeStamps.get(line) - timeStamps.get(line-1) < CINE_LOG_FREQUENCY * 2);
											ofl2 &= (timeStamps.get(line) - timeStamps.get(line-1) < CINE_LOG_FREQUENCY * 2);
											
											// if (!oneFingerLift) {System.out.print(".");}
											
											// Anyway, this counts as mode switch time
											modeSwitchTime = (int)(timeStamps.get(line) - timeStamps.get(line-1));
											modeSwitchTime2 = (int)(timeStamps.get(line) - timeStamps.get(line-1));
											
											if (timeStamps.get(line) - timeStamps.get(line-1) == 0) {
												System.out.println("ZERO");
											}
											
											gotThereAtLeastOnce = true;
										
										} else if (timeStamps.get(line) - timeStamps.get(line-1) > CINE_LOG_FREQUENCY * 2) {
											
											// There's just been a time lapse in Precise mode.
											// If the previous mode switch is close enough, ... ?
											// By default we consider one-finger lifts
											
											if (line > 1
													&& modes.get(line - 2).compareTo(MODE.COARSE) == 0) {
												
												oneFingerLift = false;
												// System.out.print("_");
												
												modeSwitchTime += timeStamps.get(line) - timeStamps.get(line-1);
												
											}
											
											for (int j = line-1 ; j > 0 ; j--) {
												/*
												if (modes.get(j).compareTo(MODE.COARSE) == 0) {
													
													// Mode switch
													// If the time elapsed in Precise mode between the mode switch and
													// the time lapse is too long, it's a normal Precise phase.
													// If it's short enough, there's been a 
													
													if (timeStamps.get(line-1) - timeStamps.get(j+1) < CINE_LOG_FREQUENCY * 4) {
														
														oneFingerLift = false;
														System.out.print("_");
														
														modeSwitchTime += timeStamps.get(line) - timeStamps.get(j);
														
													}
													
													break;
													
												}
												*/
												
											}
											
										}
										
									}
									
								}
								
								line++;
								
							}
							catch (IllegalArgumentException e) {
								// System.err.println( "Pb with value \"" + cinematicFactorValues[ cinematicFactors.get(Mode).intValue() ]  + "\"");
								// e.printStackTrace();
							}
							
						} else {
							
							modes.clear();
							timeStamps.clear();
							line = 0;
							
						}
						
					}
					
					if (!gotThereAtLeastOnce && trial >= 0) {
						System.out.println("PB HERE: P" + logFactorValues[0] + " B" + logFactorValues[2] + " T" + logFactorValues[4] + ", " + nbCinematicRead + " read");
					}
					
					logAdditionalValues.add(""+timeSpentAbove);
					logAdditionalValues.add(""+timeSpentJumping);
					logAdditionalValues.add(""+nbJumpsCC);
					logAdditionalValues.add(""+modeSwitchTime);
					logAdditionalValues.add( oneFingerLift?"OneFinger":"TwoFingers" );
					logAdditionalValues.add(""+modeSwitchTime2);
					logAdditionalValues.add( ofl2?"OneFinger":"TwoFingers" );
					
					String logLine = "P";
					
					String t = "";
					for (String lfv : logFactorValues) {
						
						// UUUUGLYYYYYYYYY
						if (lfv.equalsIgnoreCase("ARC-Pad 2")) {
							t = "ContPad";
						} else if (lfv.equalsIgnoreCase("Discrete ARC-Pad 2")) {
							t = "DiscPad";
						} else if (lfv.equalsIgnoreCase("Stare+Track")) {
							t = "ContHead";
						} else if (lfv.equalsIgnoreCase("StareScreen+Track")) {
							t = "DiscHead";
						} else {
							t = lfv;
						}
						
						logLine += t + ",";
					}
					
					for (String lav : logAdditionalValues) {
						logLine += lav + ",";
					}
					logAdditionalValues.clear();
					logFileLines.add(logLine);
					
				}
				
				lastBlockOfLastFile = block;
				
			}
			
			writeAndReset(lastParticipantOfLastFile);
			
			cinematicReader.close();
			cinematicWriter.close();
			
			logReader.close();
			logWriter.close();
			
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
	}
	
	public void removeNulls(String[] input) {
		
		for (int j = 0 ; j < input.length ; j++) {
			
			// Replacing every "null" by an empty field
			
			if (input[j].equalsIgnoreCase("null")) {
				input[j] = "";
			}
			
		}
		
	}
	
	public int myOwnDate(String fileName) {
		
		String[] split = fileName.split("_");
		String date = split[2];
		String hour = split[3];
		
		String[] splitDate = date.split("-");
		String[] splitHour = hour.split("-");
		
		try {
			return Integer.parseInt(splitDate[0]) * 43200
					 + Integer.parseInt(splitDate[1]) * 1440
					 + Integer.parseInt(splitDate[2]) * 525600
					 + Integer.parseInt(splitHour[0]) * 60
					 + Integer.parseInt(splitHour[1].substring(0, splitHour[1].length()-4));
		} catch (NumberFormatException e) {
			System.err.println("NFE: " + fileName);
			e.printStackTrace();
		} 
		
		return -1;
		
	}
	
	public void writeAndReset(int p) throws IOException {
		
		System.out.println("Writing logs for participant " + p + "...");
		
		for (String s : logFileLines) {
			logWriter.append(s);
			logWriter.append('\n');
		}
		
		for (String s : cinematicFileLines) {
			cinematicWriter.append(s);
			cinematicWriter.append('\n');
		}
		
		System.out.println("Written.");
		
		lastLogIndexOfBlock.clear();
		lastCinematicIndexOfBlock.clear();
		
		logFileLines.clear();
		cinematicFileLines.clear();
		
		System.out.println("Reset.");
		
	}
	
	public void additionalFields(long trialStart) {
		
		/*
		 * Adding values from the logs
		 */
		
		if (cinematicFactors.get(When) != null) {
			
			/* *
			 *  Time proportion from end of dwell to end of trial
			 * */
			long when = Long.parseLong(cinematicFactorValues[ cinematicFactors.get(When).intValue() ]);
			long totalTime = Long.parseLong(logFactorValues[ logFactors.get(TimeEnd).intValue() ]) - when;
			
			cinematicAdditionalValues.add( "" + ( 1d * (when - trialStart) / (1d * totalTime) ) );
			
			/* *
			 *  Whether this proportion is superior to 1 (it happens)
			 * */
			if ( ( 1d * (when - trialStart) / (1d * totalTime) ) > 1 ) {
				cinematicAdditionalValues.add("true");
			} else {
				cinematicAdditionalValues.add("false");
			}
			
			String cineLine = "";
			for (String cfv : cinematicFactorValues) {
				cineLine += cfv + ",";
			}
			for (String cav : cinematicAdditionalValues) {
				cineLine += cav + ",";
			}
			cinematicAdditionalValues.clear();
			cinematicFileLines.add(cineLine);
			
		}
		
	}
	
	public static void main(String[] args) {
		
		String logDirectoryName = "./logs/logs/";
		String cinematicDirectoryName = "./logs/cinelogs/";
		
		File logDirectory = new File(logDirectoryName);
		File cinematicDirectory = new File(cinematicDirectoryName);
		
		FilenameFilter logsFilter = new FilenameFilter() {
			public boolean accept(File dir, String name) {
				// System.out.println(name);
				return name.startsWith("logs");
			}
		};
		FilenameFilter cinematicFilter = new FilenameFilter() {
			public boolean accept(File dir, String name) {
				// System.out.println(name);
				return name.startsWith("cine");
			}
		};
		
		String logNames[] = logDirectory.list(logsFilter);
		String logsFullNames[] = new String[logNames.length];
		
		String cinematicNames[] = cinematicDirectory.list(cinematicFilter);
		String cinematicFullNames[] = new String[cinematicNames.length];
		
		for (int i = 0 ; i < logNames.length ; i++) {
			// System.out.println(logNames[i]);
			logsFullNames[i] = logNames[i];
		}
		for (int i = 0 ; i < cinematicNames.length ; i++) {
			// System.out.println(cinematicNames[i]);
			cinematicFullNames[i] = cinematicNames[i];
		}
		
		Merger merger = new Merger();
		
		merger.merge(cinematicDirectoryName, logDirectoryName, "cinelogAll.csv", "logAll.csv", cinematicFullNames, logsFullNames);
		
		System.out.println("Done!");
		
	}
	
}
